#include "LecteurPhraseAvecTable.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseAvecTable::LecteurPhraseAvecTable(string nomFich) :
	ls(nomFich), ts() {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::programme() {
// <programme> ::= debut <seqInst> fin <EOF>

	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}


////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }
	Symbole s;
	do {
		inst();
		sauterSymCour(";");
		s = ls.getSymCour();
	} while (s == "si" || s == "tantque" || s == "repeter" || s == "pour" || s == "<VARIABLE>" || s == "lire" || s == "ecrire");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::inst() {
//<inst> ::= <affectation> | <instSi> || <instTq> || <instRepeter>
	if(ls.getSymCour()=="si")
		instSi();
	else if(ls.getSymCour()=="tantque")
		instTq();
	else if(ls.getSymCour()=="repeter")
		instRepeter();
	else if(ls.getSymCour()=="lire")
		instLire();
	else if(ls.getSymCour()=="ecrire")
		instEcrire();
	else if(ls.getSymCour()=="pour")
		instPour();
	else
		affectation();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::affectation() {
// <affectation> ::= <variable> = <expression>
	testerSymCour("<VARIABLE>");
	ts.chercheAjoute(ls.getSymCour());
	ls.suivant();
	sauterSymCour("=");
    if(ls.getSymCour()=="<CHAINE>")
		ls.suivant();
    else
        expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::expression() {
// <expression> ::= <terme> { <opAdd> <terme> }

	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-")
	{
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::facteur() {
// <facteur> ::= <entier>  |  <variable>  | <opUnaire> <expBool> | ( <expression> )
	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
	{
		ts.chercheAjoute(ls.getSymCour());
		ls.suivant();
	}
	else if (ls.getSymCour()=="-" || ls.getSymCour()=="non")
	{
		opUnaire();
		expBool();
	} else if (ls.getSymCour()=="(") {
		ls.suivant();
		expBool();
		sauterSymCour(")");
	} else
		erreur("<facteur>");
}

void LecteurPhraseAvecTable::relation()
//	  <relation> ::= <expression> [<opRel> <expression>] {et <expression> [<opRel> <expression>]}
{
	expression();
	if(ls.getSymCour() == "<" || ls.getSymCour() == ">" || ls.getSymCour() == ">=" || ls.getSymCour() == "<=" || ls.getSymCour() == "==" || ls.getSymCour() == "!=")
	{
		opRel();
		expression();
	}
	while(ls.getSymCour() == "et")
	{
		sauterSymCour("et");
		expression();
		if(ls.getSymCour() == "<" || ls.getSymCour() == ">" || ls.getSymCour() == ">=" || ls.getSymCour() == "<=" || ls.getSymCour() == "==" || ls.getSymCour() == "!=")
		{
			opRel();
			expression();
		}
	}
}

void LecteurPhraseAvecTable::opUnaire()
//	  <opunaire> ::= - | non
{
	if(ls.getSymCour()== "-" || ls.getSymCour() == "non")
	{
		ls.suivant();
	}
	else
		erreur("<opUnaire>");
}

void LecteurPhraseAvecTable::opRel()
//		 <opRel> ::= == | != | >= | <= | > | <
{
	if(ls.getSymCour() == "==" || 
		ls.getSymCour() == ">" || 
		ls.getSymCour() == "<" || 
		ls.getSymCour() == ">=" || 
		ls.getSymCour() == "<=" || 
		ls.getSymCour() == "!=")
	{
		ls.suivant();
	}
	else
		erreur("<opRel>");
}

void LecteurPhraseAvecTable::expBool()
//<expBool> ::= <relation> { ou <relation> }
{
	relation();
	while (ls.getSymCour()=="ou")
	{
		sauterSymCour("ou");
		relation();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opAdd()
// <opAdd> ::= + | - 
{
	if (ls.getSymCour()=="+" || ls.getSymCour()=="-")
		ls.suivant();
	else
		erreur("<opAdd>");
}

void LecteurPhraseAvecTable::opMult()
// <opMult> ::= * | /
{
	if (ls.getSymCour()=="*" || ls.getSymCour()=="/")
		ls.suivant();
	else
		erreur("<opMult>");
}

void LecteurPhraseAvecTable::terme()
// <terme> ::= <facteur> { <opMult> <facteur> }
{
	facteur();
	while(ls.getSymCour() == "*" || ls.getSymCour() == "/")
	{
		ls.suivant();
		facteur();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}

void LecteurPhraseAvecTable::instLire()
{
	sauterSymCour("lire");
	sauterSymCour("(");
	if(ls.getSymCour()=="<VARIABLE>")
	{
		ts.chercheAjoute(ls.getSymCour());
		ls.suivant();
	}
	else
		erreur("Expected : <variable>");
	sauterSymCour(")");
}

void LecteurPhraseAvecTable::instEcrire()
{
	sauterSymCour("ecrire");
	sauterSymCour("(");
	if(ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<CHAINE>")
	{
		ts.chercheAjoute(ls.getSymCour());
		ls.suivant();
	}
	else
		erreur("Expected : <variable> || <chaine>");
	sauterSymCour(")");
}

void LecteurPhraseAvecTable::instPour()
//    <instPour> ::= pour ( <affectation> ; <expBool> ; <affectation> ) <seqInst> finpour
{
	sauterSymCour("pour");
	sauterSymCour("(");
	affectation();
	sauterSymCour(";");
	expBool();
	sauterSymCour(";");
	affectation();
	sauterSymCour(")");
	seqInst();
	sauterSymCour("finpour");
}

void LecteurPhraseAvecTable::instSi()
//		<instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> } [ sinon <seqInst> ] finsi
{
	ls.suivant();
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
	seqInst();
	while(ls.getSymCour()=="sinonsi")
	{
		sauterSymCour("sinonsi");
		sauterSymCour("(");
		expBool();
		sauterSymCour(")");
		seqInst();
	}
	if(ls.getSymCour()=="sinon")
	{
		sauterSymCour("sinon");
		seqInst();
	}
	sauterSymCour("finsi");
}

void LecteurPhraseAvecTable::instTq()
//		<instTq> ::= tantque ( <expBool> ) <seqInst> fintantque
{
	ls.suivant();
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
	seqInst();
	sauterSymCour("fintantque");
}

void LecteurPhraseAvecTable::instRepeter()
 // <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
{
	ls.suivant();
	seqInst();
	sauterSymCour("jusqua");
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
}